package packet;
import java.io.*;
import java.net.*;
import java.nio.*;
import java.nio.channels.*;
import java.nio.charset.*;
import java.util.*;

/** Hlavní třída jednoduchého HTTP Serveru. */
public class SimpleHTTPServer {

    public static final int PORT = 10997;

    /** Univerzální odpoveď */
    public static final String RESPONSE = "HTTP/1.0 200 OK\r\n"
        + "Connection: closed\r\n"
        + "Content-Type: text/plain\r\n"
        + "Content-length: 20\r\n"
        + "\r\n"
        + "Simple HTTP server.\n";

    private ServerSocketChannel ssc;
    private Selector selector;
    private CharsetDecoder decoder;
    private ByteBuffer buffer;

    public void run() {
        try {
            ssc = ServerSocketChannel.open(); //otevřít serverový kanál
            ssc.configureBlocking(false); //vypnout blokování
            selector = Selector.open(); //otevřít selektor
            ssc.register(selector, SelectionKey.OP_ACCEPT); //přidat kanál do selektoru
            ssc.socket().bind(new InetSocketAddress("0.0.0.0", PORT)); //připojit serverový soket
            decoder = Charset.forName("US-ASCII").newDecoder(); //vytvořit dekóder pro ASCII
            buffer = ByteBuffer.allocateDirect(256); //alokovat bajtový buffer

            while(ssc.isOpen()) {
                selector.select(); //zablokovat vlákno, dokud není selektor aktivní
                Set<SelectionKey> keys = selector.selectedKeys(); //získat vybrané prvky SelectionKey
                Iterator<SelectionKey> i = keys.iterator();
                while(i.hasNext()) { //projít množinu
                    SelectionKey key = i.next();
                    i.remove();
                    Channel chan = key.channel(); //získat kanál
                    if(chan == ssc) { //pokud je to serverový kanál, připojil se nový klient
                        SocketChannel client = ssc.accept(); //přijmout klienta
                        if(client != null) { //pokud se někdo opravdu připojil
                            client.configureBlocking(false); //vypnout blokování
                            client.register(selector, SelectionKey.OP_READ, new StringBuffer()); //a přidat do selektoru
                        }
                    }
                    else { //aktivní je kanál nějakého z klientů
                        SocketChannel client = (SocketChannel)chan;
                        int read = client.read(buffer); //přečíst data
                        if(read == -1) { //ukončeno spojení
                            key.cancel(); //vyřadit ze selektoru
                            client.close(); //zavřít kanál
                            continue;
                        }
                        StringBuffer sb = (StringBuffer)key.attachment(); //získat HTTP požadavek v příloze
                        buffer.flip();
                        sb.append(decoder.decode(buffer).toString()); //připojit k němu obsah bufferu
                        buffer.clear();

                        if(sb.indexOf("\r\n\r\n") != -1) { //přišel celý HTTP požadavek
                            buffer.put(RESPONSE.getBytes()); //vložit odpoveď do bufferu
                            buffer.flip();

                            int written = 0;
                            while(written < RESPONSE.length()) {
                                written += client.write(buffer); //odeslat
                            }
                            buffer.clear();
                            key.cancel(); //vyřadit ze selektoru
                            client.close(); //zavřít kanál
                        }
                    }
                }
            }
        }
        catch(IOException e) {
            e.printStackTrace(System.err);
        }
        finally {
            try {
                if(ssc != null) {
                    ssc.socket().close();
                    ssc.close();
                }
                if(selector != null) selector.close();
            }
            catch(IOException e) {}
        }
    }

    public static void main(String[] args) {
        new SimpleHTTPServer().run();
    }
} 